package com.kgcx.coupon.service;


import com.alibaba.fastjson.util.TypeUtils;
import com.github.pagehelper.PageHelper;
import com.kgcx.common.bean.RequestData;
import com.kgcx.common.client.opc.pojo.PriceActualPrice;
import com.kgcx.common.client.order.OrderClient;
import com.kgcx.common.client.order.pojo.Order;
import com.kgcx.common.client.price.PriceClient;
import com.kgcx.common.constant.Cons;
import com.kgcx.common.exception.BusinessException;
import com.kgcx.common.utils.CollectionUtils;
import com.kgcx.common.utils.UUIDUtils;
import com.kgcx.coupon.domain.CouponInfo;
import com.kgcx.coupon.domain.CouponType;
import com.kgcx.coupon.mapper.CouponInfoMapper;
import com.kgcx.dbutils.domain.BaseDomain;
import com.kgcx.dbutils.utils.CityUtils;
import com.kgcx.dbutils.utils.PageUtils;
import com.xiaoleilu.hutool.util.RandomUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;


@Service
public class CouponInfoService {
    @Autowired
    private CouponInfoMapper couponInfoMapper;

    @Autowired
    private CouponTypeService couponTypeService;

    @Autowired
    private OrderClient orderClient;

    @Autowired
    private PriceClient priceClient;


    @Transactional(rollbackFor = Exception.class)
    public void addCoupon(CouponInfo couponInfo) {
        couponInfoMapper.insertSelective(couponInfo);
    }

    @Transactional(rollbackFor = Exception.class)
    public void addCouponByType(Long customerId, Long couponTypeId) {
        CouponType couponType = couponTypeService.getCouponType(couponTypeId);
        CouponInfo couponInfo = BaseDomain.getInstance(CouponInfo.class);
        couponInfo.setCustomerId(customerId);
        couponInfo.setAvailableCity(couponType.getAvailableCity());
        couponInfo.setCity(CityUtils.getNamesByIds(couponType.getAvailableCity()));
        couponInfo.setFareType(couponType.getFareType());
        couponInfo.setMoney(couponType.getMoney());
        couponInfo.setTrigger(couponType.getTrigger());
        couponInfo.setOrderType(couponType.getOrderType());
        couponInfo.setOrderChannel(couponType.getOrderChannel());
        couponInfo.setUseType(couponType.getUserType());
        couponInfo.setVehiclePurpose(couponType.getVehiclePurpose());
        couponInfo.setState(CouponInfo.STATE_UNUSED);
        couponInfo.setName(couponType.getCouponName());
        String numbered = couponType.getNumbered();
        if (CouponType.CODE_TYPE_BY_TIME.equals(couponType.getCodeType())) {
            couponInfo.setCode(numbered + "_" + System.currentTimeMillis());
        } else {
            couponInfo.setCode(numbered + "_" + RandomUtil.randomUUID());
        }
        if (CouponType.VALIDITY_TYPE_PERIOD.equals(couponType.getUseValidityType())) {
            couponInfo.setEffTime(couponType.getValidityStartTime());
            couponInfo.setExpTime(couponType.getValidityEndTime());
        } else {
            Integer invalidDate = couponType.getInvalidDate();
            LocalDate nowDate = LocalDate.now();
            LocalDateTime startOfDay = nowDate.atStartOfDay();
            LocalDateTime expDateTime = nowDate.plusDays(invalidDate).atTime(23, 59, 59);
            couponInfo.setEffTime(Timestamp.valueOf(startOfDay));
            couponInfo.setExpTime(Timestamp.valueOf(expDateTime));
        }
        this.addCoupon(couponInfo);
    }


    public CouponInfo getCouponInfo(Long kid) {
        return couponInfoMapper.selectByPrimaryKey(kid);
    }

    public List<CouponInfo> getCouponInfoList(RequestData rd) {
        PageUtils.page(rd);
        PageHelper.orderBy(rd.getOrderBy());
        return couponInfoMapper.selectActive(BaseDomain.buildSelectDomain(rd, new CouponInfo()));
    }


    @Transactional(rollbackFor = Exception.class)
    public void removeCouponInfo(Long kid) {
        CouponInfo couponInfo = new CouponInfo();
        couponInfo.setKid(kid);
        couponInfo.setStatus(Cons.COMMON_STATUS_DELETE);
        couponInfoMapper.updateByPrimaryKeySelective(couponInfo);
    }


    @Transactional(rollbackFor = Exception.class)
    public void updateCouponInfo(CouponInfo couponInfo) {
        couponInfoMapper.updateByPrimaryKeySelective(couponInfo);
    }

    /**
     * 分页查询优惠券信息
     *
     * @return
     */
    public List<CouponInfo> queryUsableCoupon(RequestData rd) {
        PageUtils.page(rd);
        //推荐规则：可用代金券里面面额最大有限，面额相同则快过期的优先。
        PageHelper.orderBy("money desc,exp_time asc");
        CouponInfo couponInfo = BaseDomain.buildSelectDomain(rd, new CouponInfo());
        couponInfo.setState(CouponInfo.STATE_UNUSED);
        Long planDepartTime = rd.getLong("planDepartTime");
        if (null == planDepartTime) {
            planDepartTime = System.currentTimeMillis();
        }
        Timestamp planDepartTimestamp = new Timestamp(planDepartTime);
        couponInfo.setExpTimeGe(planDepartTimestamp);
        couponInfo.setEffTimeLe(planDepartTimestamp);
        return couponInfoMapper.selectActive(couponInfo);
    }

    /**
     * 分页查询优惠券信息
     *
     * @return
     */
    public List<CouponInfo> queryUsableCouponByOrderNo(RequestData rd) {

        String orderNo = rd.getString("orderNo");
        if (StringUtils.isNotBlank(orderNo)) {
            Order order = orderClient.getByOrderNo(orderNo);
            if (null != order) {
                List<CouponInfo> list = new ArrayList<>();
                Integer bindCouponId = order.getCouponId();
                if (null != bindCouponId && rd.getPageNum() == 1) {
                    //如果是第一页则在列表前塞一条已绑定的优惠卷
                    CouponInfo bindCoupon = getCouponInfo(bindCouponId.longValue());
                    if (null != bindCoupon) {
                        list.add(bindCoupon);
                    }
                }
                CouponInfo couponInfo = new CouponInfo();
                couponInfo.setCustomerId(order.getPlacingUserId());
                couponInfo.setVehiclePurposeOot(order.getBookModel().toString());
                couponInfo.setAvailableCityOot(order.getPlanOrigCityId().toString());
                couponInfo.setOrderTypeOot(order.getOrderType().toString());
                couponInfo.setFareTypeOot(order.getFareType().toString());
                couponInfo.setOrderChannelOot(order.getOrderChannel().toString());
                couponInfo.setUseTypeOot(order.getIsSelf().toString());
                couponInfo.setExpTimeGe(order.getPlanDepartTime());
                couponInfo.setEffTimeLe(order.getPlanDepartTime());
                couponInfo.setState(CouponInfo.STATE_UNUSED);
                Long trigger = rd.getLong("trigger");
                if (trigger == null) {
                    PriceActualPrice priceActualPrice = priceClient.getPriceActualPriceByOrderId(orderNo);
                    if (null != priceActualPrice) {
                        trigger = priceActualPrice.getTotalMoney();
                    }
                }
                couponInfo.setTriggerLe(trigger);
                PageUtils.page(rd);
                //推荐规则：可用代金券里面面额最大有限，面额相同则快过期的优先。
                PageHelper.orderBy("money desc,exp_time asc");
                List<CouponInfo> couponInfos = couponInfoMapper.selectActive(couponInfo);
                if (CollectionUtils.isNotEmpty(couponInfos)) {
                    for (CouponInfo info : couponInfos) {
                        //如果不是绑定优惠卷，或者不是第一页才加入列表，为了不与第一页的绑定优惠卷重复
                        if (!TypeUtils.castToInt(info.getKid()).equals(bindCouponId) || rd.getPageNum() != 1) {
                            list.add(info);
                        }
                    }
                }
                return list;


            } else {
                throw new BusinessException("");
            }
        }
        return null;
    }

    /**
     * 分页查询用户优惠券信息
     *
     * @return
     */
    public List<CouponInfo> queryUserCoupon(RequestData rd) {
        PageUtils.page(rd);
        //排序规则：按领取时间最近的在前排序，领取时间相同按面额最大在前排序。已经失效的或者已经使用过的代金券不做显示。
        PageHelper.orderBy("getcoupontime asc,money desc");
        CouponInfo couponInfo = BaseDomain.buildSelectDomain(rd, new CouponInfo());
        couponInfo.setState(CouponInfo.STATE_UNUSED);
        couponInfo.setExpTimeGe(new Timestamp(System.currentTimeMillis()));
        return couponInfoMapper.selectActive(couponInfo);
    }

    public void updateCouponState(Long couponId, Long state) {
        CouponInfo couponInfo = getCouponInfo(couponId);
        couponInfo.setState(state);
        updateCouponInfo(couponInfo);
    }

}
